/*print stack info at current thread*/
#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

static char *this;

// 函数用于从地址获取文件名和行号
void get_file_line(const char* addr_str, char* file_buffer, size_t file_size, int* line) {
    char cmd[256];
    sprintf(cmd, "addr2line -e %s %s", this, addr_str); // 假设可执行文件名为a.out，需根据实际情况修改
    FILE* pipe = popen(cmd, "r");
    if (fgets(file_buffer, file_size, pipe) != NULL) {
        // 解析fgets读取的行，提取文件名
        char* fileNameEnd = strchr(file_buffer, ':');
        if (fileNameEnd) {
            *fileNameEnd = '\0'; // 截断字符串到文件名部分
            fileNameEnd++;       // 移动到行号部分
            *line = atoi(fileNameEnd); // 将行号字符串转换为整数
        }
    }
    pclose(pipe);
}

void print_trace(void)
{
    void *array[10];
    size_t size;
    char **strings;
    size_t i;

    size = backtrace(array, 10);
    strings = backtrace_symbols(array, size);

    printf("Obtained %zd stack frames.\n", size);

    for (i = 0; i < size; i++){
		char fileName[256];
        int lineNumber;

		printf("%s ", strings[i]);
        // 提取并打印文件名和行号
        char* addrStart = strstr(strings[i], "[0x");
        if (addrStart) {
            addrStart += 3; // 跳过"[0x"
            char* addrEnd = strchr(addrStart, ']');
            if (addrEnd) {
                *addrEnd = '\0';
                get_file_line(addrStart, fileName, sizeof(fileName), &lineNumber);
                printf("    at %s:%d\n", fileName, lineNumber > 0?lineNumber-1:0);
                *addrEnd = ']'; // 恢复原字符串
            }
        }
    }
  

    free(strings);
}

void functionA(void) {
    print_trace();
}

int main(int argc, char *argv[]) {
	this = argv[0];
    functionA();
    return 0;
}
